
<template>
    <div ref="videoPlayer" style="position:relative;">
      <Artplayer class="art-box" @get-instance="getInstance" :option="option" :style="style" />  
    </div>
  </template>
  
  <script setup>
  import { onMounted, reactive, ref, onUnmounted } from 'vue'
  import Artplayer from "./Artplayer.vue";
  const videoPlayer = ref(null)
  // 修改部分变量
    const watermarkText = ref('ID:USER_123456') // 单行水印文字
    const position = reactive({ x: 0, y: 20 })
    const speed = reactive({ dx: 1, dy: 1}) // 移动速度
    let animationFrameId = null
  const w = 600, h = 400
  const cssText = `
              display: block !important;
              visibility: visible !important;
              opacity: 1 !important;
              position: absolute !important;
              z-index: 999 !important;
              pointer-events: none !important;
              top: 0 !important;
            `
  const style = {
    width: w+"px",
    height: h+"px",
  }
  const canvas_box = ref(null)
  const option = reactive({
    // url: "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
    url: "https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/hls/xgplayer-demo.m3u8",
    // setting: true,
    fullscreen: true,
  })
  onMounted(() => {
    init()
  })
  document.addEventListener('fullscreenchange', () =>handleFullscreenChange())
  // 在组件卸载时停止动画
  onUnmounted(() => {
    if (animationFrameId) cancelAnimationFrame(animationFrameId)
  })
  function init() {
    let canvas = canvasFunc()
    canvas_box.value = canvas
    // 修改事件监听部分
    const initWatermark = () => {
        checkWatermarkStyle(canvas)
        updateWatermark()
    }
    initWatermark()
    MutationObserverFunc(canvas)
  }
  function canvasFunc() {
    // 创建水印画布 =====================================================
    const canvas = document.createElement('canvas')
    // 给canvas添加一个id
    canvas.id = 'watermark'
    canvas.style.cssText = cssText
    // 挂载到视频容器
    console.log(videoPlayer.value)
    videoPlayer.value.appendChild(canvas)
    return canvas
  }
  // 动态更新水印
  function updateWatermark() {
      let canvas = canvas_box.value
      if (!canvas) return
      const ctx = canvas.getContext('2d')
      if (!ctx) {
        console.error('无法获取canvas上下文')
        return
      }
      
      // 获取当前容器尺寸
        const container = document.fullscreenElement || videoPlayer.value
        canvas.width = container.offsetWidth
        canvas.height = container.offsetHeight
      
      // 动态水印
      createDenseWatermark(ctx, canvas.width, canvas.height, document.fullscreenElement) // 绘制水印
      animationFrameId = requestAnimationFrame(updateWatermark) // 递归调用
  }
  
  // 创建移动水印
  function createDenseWatermark(ctx, width, height, fullscreenElement) {
    ctx.clearRect(0, 0, width, height)
    ctx.save()
    ctx.font = '24px Arial'
    ctx.fillStyle = 'rgba(255,255,255,0.5)'
    // 更新位置
    if (fullscreenElement) {
        const isNearEdge = position.y <= 200 || position.y >= height - 200;
        position.x += speed.dx * (isNearEdge ? 4 : 1);
        position.y += speed.dy * (isNearEdge ? 4 : 1);
    } else {
        position.x += speed.dx;
        position.y += speed.dy;
    }
    
    // 边界检测
    if (position.x > width - ctx.measureText(watermarkText.value).width || position.x < 0) {
        speed.dx *= -1
    }
    if (position.y > height || position.y < 20) { // 字体高度为20，字体的坐标是以底部为准的, 所以position.y=0的时候，是看不到字的
        speed.dy *= -1
    }

    ctx.fillText(watermarkText.value, position.x, position.y)
    ctx.restore()
  }
  // 检查样式是否被修改
  function checkWatermarkStyle(canvas) {
    const check = () => {
      const computedStyle = getComputedStyle(canvas)
      const violations = [
        computedStyle.position !== 'absolute',
        computedStyle.display === 'none',
        computedStyle.visibility === 'hidden',
        computedStyle.top !== '0px !important',
        computedStyle.left !== '0px !important',
        computedStyle.right !== '0px !important',
        parseFloat(computedStyle.opacity) < 0.5
      ]
  
      if (violations.some(v => v)) { // 如果有违反，重新设置样式
        canvas.style.cssText = cssText
      }
    }
    // 每秒检查10次（平衡性能与安全性）
    setInterval(check, 100)
  }
  // 使用MutationObserver保护水印元素不被f12删除
  function MutationObserverFunc(canvas) {
    const observer = new MutationObserver(mutations => {
      mutations.forEach(mutation => {
        // 防御display属性修改
        // if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
        //   const currentDisplay = getComputedStyle(canvas).display
        //   if (currentDisplay === 'none') {
        //     canvas.style.display = 'block'
        //   }
        // }
        // 禁止在f12后对元素进行删除
        const fullscreenElement = document.fullscreenElement
        const targetContainer = fullscreenElement || videoPlayer.value
        if (!targetContainer.contains(canvas)) { // 如果canvas不在目标容器中，则重新添加
          targetContainer.appendChild(canvas)
        }
      })
    })
    // 修改观察配置
    observer.observe(document.body, {
      attributes: true,         // 观察属性变化
      attributeFilter: ['style'], // 仅观察style属性
      childList: true,          // 原有子节点观察
      subtree: true             // 原有子树观察
    })
  }
  function handleFullscreenChange() {
    if(!canvas_box.value) return
    cancelAnimationFrame(animationFrameId) // 停止动画
    resetPosition() // 重置位置
    updateWatermark() // 重新开始动画
  }
  function resetPosition() {
    position.x = 0
    position.y = 20
  }
  function getInstance(art) {
    console.info(art);
  }
  let str = repeatFunc("hi",10)
  console.log(str)
  function repeatFunc(str, num) {
    let count = str.length * num

    let chunkLimit = 10*1024, chunkMax=count
    if(count > chunkLimit) {
      chunkMax = chunkLimit / str.length * str.length
      if(chunkMax === 0) {
        chunkMax = str.length
      }
    }

    let charArr = str.split("")
    while(charArr.length < count) {
      let chunk = count - charArr.length
      if(chunk > charArr.length) {
        chunk = charArr.length
      }
      if(chunk > chunkMax) {
        chunk = chunkMax 
      }
      charArr.push(...charArr.slice(0, chunk))
    }
    return charArr.join("")
  }
  </script>
  <style scoped>
  .read-the-docs {
    color: #888;
  }
   /* 添加全局不可覆盖样式 */
   #watermark {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
    pointer-events: none !important;
  }
  
/* 移除原有全屏样式，添加新样式 */
#watermark {
  pointer-events: none !important;
  transition: all 0.3s; /* 添加平滑移动效果 */
}
  </style>
  